﻿/*
  --=================================================================================================================
  --=================================================================================================================
  -- Fichier          :	FacadePV.cs
  -- Objet			  :	Facade des PV permettant à la partie VM d'avoir un unique point d'entré pour le modèle.
  -- Auteur			  :	S. Le Gouellec
  -- Date de création : 07/2014
  --                              :
  --                              :
  -- Notes spéciales		  :
  -- Historique			  :
  ----------------------------------------------------------------------------------------------
  -- |     Code    |  Vers. |   Date   | Auteur	|                  Description
  -- |  Dem/inc/pr |  	    |          |        |         
  -- -------------------------------------------------------------------------------------------
  -- |             |   1.0  | 07/2014  |  SLE	| Création
  -- |	           |	    |	       |        |
  --=================================================================================================================
  --=================================================================================================================
*/

using GeneralServices.Data;
using ModelEntities.Adapter;
using Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ModelEntities.Facade
{
    /// <summary>
    /// Classe singleton : Permet d'avoir un unique point d'accès au modèle des views models.
    /// Propose des méthodes permettant de récupérer des objet métiers qui encapsulent des objets mappé de la BDD.
    /// </summary>
    public class FacadePV
    {
        #region Attribut(s)

        /// <summary>
        /// DbContext de la base de donnée (ici , ReprisePV)
        /// </summary>
        private EntitiesReprisePV contextReprisePV;

        /// <summary>
        /// Instance permettant d'implémenter le pattern Singleton
        /// </summary>
        private static FacadePV instance = null;

        /// <summary>
        /// Objet permettant de locker cet objet , en cas d'accès concurrent
        /// </summary>
        private static object _lock = new object();

        /// <summary>
        /// Evenement de mise à jour d'un PV (suppression)
        /// </summary>
        public EventHandler<PVEventArgs> UpdatePVs;

        #endregion

        #region Propriété(s)

        /// <summary>
        /// Permet d'obtenir une seule instance de Facade dans l'application
        /// </summary>
        public static FacadePV Instance
        {
            get
            {
                lock (_lock)
                {
                    if (instance == null)
                    {
                        lock (_lock)
                            instance = new FacadePV();
                    }
                }

                return instance;
            }
        }

        #endregion

        #region Constructeur(s)

        /// <summary>
        /// Constructeur vide
        /// </summary>
        public FacadePV()
        {
            contextReprisePV = StoreApplicationDbContext.Get("ContextPV") as EntitiesReprisePV;
            //contextReprisePV = new EntitiesReprisePV();
        }

        #endregion

        #region Méthode(s)

        #region PV

        /// <summary>
        /// Retourne tous les années des PVs
        /// </summary>
        /// <returns>Liste de string regroupant les différentes années des PVs en BDD</returns>
        public List<String> GetYears()
        {
            List<int> yearsPV = new List<int>();
            DateTime dt1 = DateTime.Now;
            yearsPV = (from pv in contextReprisePV.PV_ENTETE
                       select pv.DATE_EDITION.Year).Distinct().ToList();
            DateTime dt2 = DateTime.Now;
            TimeSpan ts = dt2 - dt1;

            yearsPV.Sort();
            yearsPV.Reverse();

            List<String> rsult = new List<string>();
            foreach(int i in yearsPV)
                rsult.Add(String.Format("{0}", i));

            return rsult;
        }


        /// <summary>
        /// Permet d'obtenir un PV en fonction de sa clé primaire
        /// </summary>
        /// <param name="numPV">Numéro du PV</param>
        /// <param name="dateEmission">Date d'émission du PV</param>
        /// <param name="version">Numéro de version du PV</param>
        /// <returns>Retourne un objet métier qui encapsule un objet relationel</returns>
        public MEntetePV GetPV(String numPV, DateTime dateEmission, String version)
        {
            MEntetePV pvDTO = new MEntetePV(
                                contextReprisePV.PV_ENTETE.First(pv => pv.NO_PV.Equals(numPV)
                                                                    && pv.DATE_EDITION.Equals(dateEmission)
                                                                    && pv.VERSION.Equals(version)));
            return pvDTO;
        }

        /// <summary>
        /// Permet d'obtenir une liste de PV en fonction d'un numéro de PV
        /// </summary>
        /// <param name="numPV">Numéro du PV</param>
        /// <returns>Retourne une liste d'objet métier qui ont pour numéro de PV le numéro passé en paramètre</returns>
        public List<MEntetePV> GetPVs(String numPV)
        {
            List<MEntetePV> listPVDTO = new List<MEntetePV>();

            var listResult = from pv in contextReprisePV.PV_ENTETE
                             where pv.NO_PV.Equals(numPV)
                             select pv;

            foreach (PV_ENTETE pv in listResult)
                listPVDTO.Add(new MEntetePV(pv));

            return listPVDTO;
        }

        /// <summary>
        /// Permet d'obtenir une liste de PV en fonctiond d'une année
        /// </summary>
        /// <param name="annee">Année demandée</param>
        /// <returns>Retourne une liste de PV qui ont été émis cette année là.</returns>
        public List<MEntetePV> GetPVsbyAnnee(String annee)
        {
            List<MEntetePV> listPVDTO = new List<MEntetePV>();
            short an = Convert.ToInt16(annee);

            var listResult = contextReprisePV.PV_ENTETE.Select(pv => pv).Where(pv => pv.DATE_EDITION.Year == an);

            foreach (PV_ENTETE pv in listResult)
                listPVDTO.Add(new MEntetePV(pv));

            return listPVDTO;
        }

        /// <summary>
        /// Permet de supprimer un PV en fonction de sa clé primaire
        /// </summary>
        /// <param name="numPV">Numéro du PV</param>
        /// <param name="dateEdition">Date d'édition du PV</param>
        /// <param name="version">Numéro de version du PV</param>
        /// <returns>Retourne un booléan permettant de savoir si le PV a bien été supprimé</returns>
        public void ErasePV(String numPV, DateTime dateEdition, String version)
        {
            PV_ENTETE pvE = contextReprisePV.PV_ENTETE.First<PV_ENTETE>(p => p.NO_PV.Equals(numPV) && p.VERSION.Equals(version) && p.DATE_EDITION.Equals(dateEdition));
            contextReprisePV.PV_ENTETE.Remove(pvE);
        }

        /// <summary>
        /// Permet de supprimer un PV en fonction de sa clé primaire
        /// </summary>
        /// <param name="pv">PV a supprimé</param>
        public void ErasePV(MEntetePV pv)
        {
            ErasePV(pv.NoPV, pv.DateEdition, pv.Version);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public List<PV_PARAMETRAGE> GetParams()
        {
            return contextReprisePV.PV_PARAMETRAGE.
                OrderBy(param => param.NO_SEQUENCE).ToList<PV_PARAMETRAGE>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pseudo"></param>
        /// <returns></returns>
        public PV_UTILISATEUR GetUser(String pseudo)
        {
            return contextReprisePV.PV_UTILISATEUR.First(user => user.CODE_UTILISATEUR.Equals(pseudo));
        }

        #endregion

        #region Commits

        public void CommitAfterErase(MEntetePV pv)
        {
            Commit();

            if (UpdatePVs != null)
                UpdatePVs(this, new PVEventArgs { PV = pv });
        }

        private void Commit()
        {
            contextReprisePV.SaveChanges();
        }

        #endregion

        #endregion

    }
}
